<template>
  <el-form
    ref="searchForm"
    :model="modelValue"
    :rules="rules"
    :label-width="labelWidth"
    inline
    @submit.prevent
    class="-mb-15px"
  >
    <template v-for="(item, index) in config" :key="item.key">
      <el-form-item
        v-if="index + 1 < cols || (index + 1 >= cols && searchAreaShow)"
        :label="item.label"
        :prop="item.key"
        :label-width="item.labelWidth"
      >
        <template v-if="item.slotName">
          <slot :name="item.slotName" :item="item" />
        </template>
        <template v-else>
          <component
            :is="getComp(item)"
            v-bind="getAttrs(item)"
            @keyup.enter="item.is === 'input' && onSearch()"
            class="!w-240px"
          />
        </template>
      </el-form-item>
    </template>

    <el-form-item label-width="0px">
      <ElButton type="primary" @click="onSearch">
        <Icon class="mr-5px" icon="ep:search" />
        {{ searchLabel }}
      </ElButton>
      <ElButton v-if="showRest" @click="onReset">
        <Icon class="mr-5px" icon="ep:refresh" />
        {{ resetLabel }}
      </ElButton>
      <ElButton v-if="config.length >= cols" type="text" @click="searchAreaShow = !searchAreaShow">
        <Icon :icon="searchAreaShow ? 'ep:d-arrow-left' : 'ep:d-arrow-right'" class="mr-4px" />
        {{ searchAreaShow ? '收起' : '展开' }}
      </ElButton>
    </el-form-item>
  </el-form>
</template>

<script lang="ts" setup>
import { ElForm, ElButton } from 'element-plus'
import { omit, reduce, each } from 'lodash-es'
import { getCustomInput } from './getCustomInput'
import { dayjsFormat } from '@/utils/dateUtil'

interface ConfigItem {
  label: string
  key: string
  is: string
  slotName?: string
  labelWidth?: string
  defaultValue?: any
  [key: string]: any
}

const props = defineProps({
  config: {
    type: Array as () => ConfigItem[],
    default: () => []
  },
  modelValue: {
    type: Object as () => Record<string, any>,
    default: () => ({})
  },
  rules: {
    type: Object as () => Record<string, any>,
    default: () => ({})
  },
  labelWidth: {
    type: String,
    default: '82px'
  },
  cols: {
    type: Number,
    default: 14
  },
  searchLabel: {
    type: String,
    default: '搜索'
  },
  resetLabel: {
    type: String,
    default: '重置'
  },
  showRest: {
    type: Boolean,
    default: true
  },
  autoSearch: {
    type: Boolean,
    default: true
  }
})

const emit = defineEmits(['field:change', 'search', 'reset'])

const searchAreaShow = ref(false)

const onModelValueChangeByKey =
  (key: string) =>
  (...value: any[]) => {
    emit('field:change', key, ...value)
  }

const onSearch = () => {
  emit('search')
}

const onReset = () => {
  const initValue = reduce(
    props.config,
    (memo, item) => {
      memo[item.key] = item.defaultValue !== undefined ? item.defaultValue : null
      return memo
    },
    {} as Record<string, any>
  )
  each(initValue, (v, k) => {
    onModelValueChangeByKey(k)(v)
  })
  emit('reset')
  onSearch()
}

const getAttrs = (item: ConfigItem) => {
  // console.log('getAttrs：', item)
  const { is, key, ...rest } = item
  const attrs = omit(rest, ['label', 'slotName'])
  const onValueChange = onModelValueChangeByKey(key)
  let additions = {
    modelValue: props.modelValue[key],
    onInput: onValueChange,
    clearable: true
  }
  if (typeof is === 'string') {
    switch (is) {
      case 'input':
        Object.assign(additions, {
          onClear: () => {
            onValueChange('')
            onSearch()
          }
        })
        break
      case 'select':
      case 'cascader':
        Object.assign(additions, {
          onChange: (args: any[]) => {
            onValueChange(args)
            onSearch()
          }
        })
        break
      case 'dateRangePicker':
        Object.assign(additions, {
          /** onChange事件正常点击日期不触发，点击'清空'的时候又会触发。点击'清空'的时候onClear事件又不触发...
           * 1.用onCalendarChange代替onChange选值的效果
           * 2.用onChange代替onClear清空时候的效果
           */
          onCalendarChange: (args: [Date, null | Date]) => {
            if (!!args[0] && !!args[1]) {
              console.log('onCalendarChange：', args)
              const values = [
                dayjsFormat(args[0], item?.valueFormat),
                dayjsFormat(args[1], item?.valueFormat)
              ]
              onValueChange(values)
              onSearch()
            }
          },
          onChange: (args: any[]) => {
            onValueChange(args)
            onSearch()
          }
        })
        break
      default:
        break
    }
  }
  return { ...additions, ...attrs }
}

const getComp = (item: ConfigItem) => {
  return getCustomInput(item.is)
}

onMounted(() => {
  if (props.autoSearch) onSearch()
})
</script>
